package mockdata

import (
	"encoding/json"
	"fmt"
	"gitee.com/captials-team/ubdframe/src/common/utils"
	"github.com/Knetic/govaluate"
	"github.com/spf13/cast"
	"io/ioutil"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)

func NewMockDataRule(s string) MockDataRule {
	var d MockDataRule
	if s == "" {
		return d
	}
	if err := json.Unmarshal([]byte(s), &d); err != nil {
		panic(err)
	}

	if d.WhiteMap == nil {
		d.WhiteMap = map[string]bool{}
	}
	for _, v := range d.WhiteList {
		d.WhiteMap[v] = true
	}
	for k, v := range d.ComplexRules {
		v.Index = int64(k) + 1
	}
	return d
}

func NewMockDataRuleFromFile(file string) MockDataRule {
	var s = ``
	if file != "" && utils.FilePathExist(file) {
		tmp, err := ioutil.ReadFile(file)
		if err == nil {
			s = string(tmp)
		}
	}
	if s == "" {
		return MockDataRule{}
	}

	return NewMockDataRule(s)
}

// MockDataRule  模拟仿真数据规则配置
// 目前暂不支持并发下处理
type MockDataRule struct {
	WhiteList []string `json:"whiteList"` //白名单，在白名单中的才可上传，空表示不限制

	SampleRules map[string]*SampleRuleItem `json:"sample_rules"` //规则-随机取样本值
	RandRules   map[string]*RandRuleItem   `json:"rand_rules"`   //规则-取随机一个值

	ComplexRules []*ComplexRuleItem `json:"complex_rules"` //复杂规则

	WhiteMap map[string]bool `json:"-"`
}

type RuleCalcExtendParams map[string]interface{}

// MergeCalcExtendParams 合并计算扩展参数
func MergeCalcExtendParams(ps ...RuleCalcExtendParams) RuleCalcExtendParams {
	p := make(map[string]interface{})
	if len(ps) > 0 {
		for _, tmp := range ps {
			if tmp == nil {
				continue
			}
			for k, v := range tmp {
				p[k] = v
			}
		}
	}
	return p
}

// GetData 获取值
//
//		key=对应字段名，value=默认值
//	 params，额外的计算参数
//		返回值： 对应值，是否需要使用
func (r MockDataRule) GetData(key string, value interface{}, params RuleCalcExtendParams) (interface{}, bool) {
	//有白名单且不在里面就不处理
	if r.WhiteMap != nil {
		if _, exist := r.WhiteMap[key]; len(r.WhiteMap) > 0 && !exist {
			return value, false
		}
	}

	//样本规则
	if r.SampleRules != nil {
		if rule, exist := r.SampleRules[key]; exist {
			return rule.GetData(key, value, params)
		}
	}

	//随机规则
	if r.RandRules != nil {
		if rule, exist := r.RandRules[key]; exist {
			return rule.GetData(key, value, params)
		}
	}

	//复杂规则
	for _, v := range r.ComplexRules {
		result, ok := v.GetData(key, value, params)
		if ok {
			return result, ok
		}
	}

	return value, false
}

// SampleRuleItem 样本随机规则
type SampleRuleItem []interface{}

func (r SampleRuleItem) GetData(key string, value interface{}, params RuleCalcExtendParams) (interface{}, bool) {
	if len(r) == 0 {
		return value, false
	}
	return r[utils.TrueScopeRand(0, int64(len(r)))], true
}

// RandRuleItem 随机取值规则
type RandRuleItem struct {
	Min  float64 `json:"min"`
	Max  float64 `json:"max"`
	Step float64 `json:"step"`
}

func (r RandRuleItem) GetData(key string, value interface{}, params RuleCalcExtendParams) (interface{}, bool) {
	if r.Max < r.Min {
		return value, false
	}
	if r.Max == r.Min {
		return r.Max, true
	}
	if r.Step == 0 {
		r.Step = 1
	}
	l := (r.Max - r.Min) / r.Step
	if int64(l) < 1 {
		l = 1
	}
	return r.Min + float64(utils.TrueScopeRand(0, int64(l)))*r.Step, true
}

// ComplexRuleItem 复杂规则
type ComplexRuleItem struct {
	Index int64 //序列值，从1开始，自动生成
	Execs int64 //执行次数

	Names      []string `json:"names"`      //命中名称
	Condition  string   `json:"condition"`  //执行条件
	Expression string   `json:"expression"` //计算公式
}

func (r *ComplexRuleItem) GetData(key string, value interface{}, params RuleCalcExtendParams) (interface{}, bool) {
	if !r.inNames(key) {
		return value, false
	}
	if !r.inCondition(key) {
		return value, false
	}

	return r.calcExpression(key, value, params)
	//return value, true
}

func (r *ComplexRuleItem) inNames(key string) bool {
	for _, v := range r.Names {
		if v == key {
			return true
		}
	}
	return false
}

func (r *ComplexRuleItem) inCondition(key string) bool {
	if r.Condition == "" {
		return true
	}
	expression, err := govaluate.NewEvaluableExpressionWithFunctions(r.Condition, ruleFunctions)
	if err != nil {
		return false
	}

	parameters := NewRuleExpressionParameters()
	parameters["key"] = key

	result, err := expression.Evaluate(parameters)
	if err != nil {
		return false
	}

	t, _ := result.(bool)
	return t
}

// calcExpression 计算公式
//
//		key:当前选择key
//		value: 默认值
//	 params: 额外计算参数
func (r *ComplexRuleItem) calcExpression(key string, value interface{}, params RuleCalcExtendParams) (interface{}, bool) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(r.Expression, "err", err)
			panic(err)
		}
	}()
	defer func() {
		r.Execs++
	}()
	if r.Expression == "" {
		return value, false
	}

	dynamic := DynamicRuleFunctions(&MockRuntimeInfo{
		Execs: r.Execs,
	})
	expression, err := govaluate.NewEvaluableExpressionWithFunctions(r.Expression, dynamic)
	if err != nil {
		fmt.Println("Expression=", r.Expression, "err", err)
		return value, false
	}

	parameters := NewRuleExpressionParameters()
	parameters["key"] = key

	result, err := expression.Evaluate(MergeCalcExtendParams(parameters, params))
	if err != nil {
		fmt.Println(r.Expression, "err", err)
		return value, false
	}

	return result, true
}

func NewRuleExpressionParameters() map[string]interface{} {
	parameters := make(map[string]interface{}, 8)

	parameters["timestamp"] = time.Now().Unix()
	parameters["timestamp_mill"] = time.Now().UnixMilli() //毫秒级时间戳
	parameters["timestamp_nano"] = time.Now().UnixNano()  //纳秒级时间戳
	parameters["year"] = time.Now().Year()
	parameters["month"] = time.Now().Month()
	parameters["day"] = time.Now().Day()
	parameters["hour"] = time.Now().Hour()
	parameters["minute"] = time.Now().Minute()
	parameters["second"] = time.Now().Second()
	return parameters
}

var ruleFunctions = map[string]govaluate.ExpressionFunction{
	"Sample":    _rfs.Sample,
	"Timestamp": _rfs.Timestamp,
	"Float64":   _rfs.Float64,
	"Int64":     _rfs.Int64,
	"Rand":      _rfs.Rand,
	"RandSeed":  _rfs.RandSeed,
	"KeyInt":    _rfs.KeyInt64,
	"KeyFloat":  _rfs.KeyFloat64,
}

// MockRuntimeInfo 运行时信息
type MockRuntimeInfo struct {
	Execs int64 //执行次数
}

func DynamicRuleFunctions(m *MockRuntimeInfo) map[string]govaluate.ExpressionFunction {
	if m == nil {
		return ruleFunctions
	}
	dynamicFunctions := map[string]govaluate.ExpressionFunction{}
	for k, v := range ruleFunctions {
		dynamicFunctions[k] = v
	}
	//从file自动获取value，根据当前执行次数
	dynamicFunctions["FileValues"] = func(arguments ...interface{}) (interface{}, error) {
		if len(arguments) == 1 {
			arguments = append(arguments, m.Execs)
		}
		return _rfs.ValueFromFile(arguments[0], arguments[1])
	}
	dynamicFunctions["FileFloatValues"] = func(arguments ...interface{}) (interface{}, error) {
		if len(arguments) == 1 {
			arguments = append(arguments, m.Execs)
		}
		return _rfs.FloatValueFromFile(arguments[0], arguments[1])
	}
	dynamicFunctions["FileIntValues"] = func(arguments ...interface{}) (interface{}, error) {
		if len(arguments) == 1 {
			arguments = append(arguments, m.Execs)
		}
		return _rfs.IntValueFromFile(arguments[0], arguments[1])
	}
	dynamicFunctions["FileStrValues"] = func(arguments ...interface{}) (interface{}, error) {
		if len(arguments) == 1 {
			arguments = append(arguments, m.Execs)
		}
		return _rfs.ValueFromFile(arguments[0], arguments[1])
	}
	return dynamicFunctions
}

var _rfs RuleFunctions

type RuleFunctions struct {
}

func (rfs RuleFunctions) Sample(args ...interface{}) (interface{}, error) {
	//随机取样本值
	return args[utils.TrueScopeRand(0, int64(len(args)))], nil
}

// Timestamp 返回当前秒级时间戳，args子项含义一次为：offset（可不填）
func (rfs RuleFunctions) Timestamp(args ...interface{}) (interface{}, error) {
	var offset int64
	if len(args) > 0 {
		offset = cast.ToInt64(args[0])
	}
	return int64(time.Now().Unix() + offset), nil
}

// Float64 转为float64
func (rfs RuleFunctions) Float64(args ...interface{}) (interface{}, error) {
	return utils.Interface2Float64(args[0]), nil
}

// Int64 转为int64
func (rfs RuleFunctions) Int64(args ...interface{}) (interface{}, error) {
	return utils.Interface2Int64(args[0]), nil
}

// Rand 完全随机值, args子项含义依次为: min,max,step
func (rfs RuleFunctions) Rand(args ...interface{}) (interface{}, error) {
	//随机范围取值
	if len(args) != 3 {
		return nil, fmt.Errorf("rand params invalid")
	}
	min := args[0].(float64)
	max := args[1].(float64)
	step := args[2].(float64)

	l := (max - min) / step

	return min + step*float64(utils.TrueScopeRand(0, int64(l))), nil
}

// RandSeed 根据种子进行随机数, args子项含义依次为: min,max,step,seed
func (rfs RuleFunctions) RandSeed(args ...interface{}) (interface{}, error) {
	//随机范围取值(指定种子)
	if len(args) != 4 {
		return nil, fmt.Errorf("rand params invalid")
	}
	min := args[0].(float64)
	max := args[1].(float64)
	step := args[2].(float64)

	l := (max - min) / step

	seed, _ := strconv.ParseFloat(fmt.Sprint(args[3]), 64)
	r := rand.New(rand.NewSource(int64(seed)))

	return min + step*float64(r.Int63n(int64(l)+1)), nil
}

func (rfs RuleFunctions) KeyInt64(args ...interface{}) (interface{}, error) {
	//随机范围取值(指定种子)
	if len(args) == 0 {
		return nil, fmt.Errorf("key params invalid")
	}
	s := strconv.QuoteToASCII(fmt.Sprintf("%x", args[0]))
	var number int64
	for _, v := range s {
		number += int64(v)
	}

	return number, nil
}

func (rfs RuleFunctions) KeyFloat64(args ...interface{}) (interface{}, error) {
	//随机范围取值(指定种子)
	if len(args) == 0 {
		return nil, fmt.Errorf("key params invalid")
	}
	s := strconv.QuoteToASCII(fmt.Sprintf("%x", args[0]))
	var number float64
	for _, v := range s {
		number += float64(v)
	}

	return number, nil
}

func (rfs RuleFunctions) FloatValueFromFile(args ...interface{}) (interface{}, error) {
	value, err := rfs.ValueFromFile(args...)
	if err != nil {
		return int64(0), err
	}

	return utils.Interface2Float64(value), nil
}

func (rfs RuleFunctions) IntValueFromFile(args ...interface{}) (interface{}, error) {
	value, err := rfs.ValueFromFile(args...)
	if err != nil {
		return int64(0), err
	}

	return utils.Interface2Int64(value), nil
}

func (rfs RuleFunctions) ValueFromFile(args ...interface{}) (interface{}, error) {
	if len(args) == 0 {
		return nil, fmt.Errorf("key params invalid")
	}

	file := args[0].(string)
	index := time.Now().Unix()
	if len(args) > 1 {
		index = cast.ToInt64(args[1])
	}

	//fmt.Println(file)
	bytes, err := os.ReadFile(file)
	if err != nil {
		return nil, err
	}
	s := string(bytes)
	s = strings.TrimLeft(s, "\n")
	s = strings.TrimRight(s, "\n")
	rows := strings.Split(s, "\n")
	if len(rows) == 0 {
		return "", nil
	}
	value := rows[index%int64(len(rows))] //按index取对应值
	return value, nil
}

func TestMockDataRule() MockDataRule {
	return NewMockDataRule(`
{
  "whiteList": [
  ],
  "sample_rules": {
    "RunState": ["中间","最上面"],
    "ChargeState": ["充电","放电"],
    "sample1": ["num1","num2","num3"],
    "sample2": [],
    "sample11.state": ["正常","告警","离线"]
  },
  "rand_rules": {
    "RackCellsTemp": {"max": 30, "min": 29, "step": 0.1},
    "sample3": {"max": 10, "min": 1, "step": 0.001}
  },
"complex_rules":[
{"names":["sample4","sample5"],"condition":"","expression":"1"},
{"names":["sample6","sample5"],"condition":"","expression":"'1'"},
{"names":["sample7"],"condition":"second%2==0","expression":"'xxxx'"},
{"names":["sample8"],"condition":"","expression":"Rand(0,10,0.1)+timestamp"},
{"names":["sample9"],"condition":"","expression":"Rand(0,10,0.1)+Float64(Timestamp())"},
{"names":["sample10"],"condition":"","expression":"Rand(0,10,0.1)+Rand(0,10,0.1)"},
{"names":["sample11.time"],"condition":"","expression":"Rand(0,10,0.1)+Rand(0,10,0.1)"},
{"names":["sample11.temp"],"condition":"","expression":"Rand(0,10,0.1)+Rand(0,10,0.1)"},
{"names":["sample11.cell_temp"],"condition":"","expression":"Rand(0,10,0.1)+Rand(0,10,0.1)"},

    {"names":["rack_rechargeable_cap"],"condition":"hour<=12","expression":"(12-hour)*40+20+second*1+Rand(1,10,1)"},
    {"names":["rack_rechargeable_cap"],"condition":"hour>12","expression":"500-(hour-12)*40-second*1+Rand(1,10,1)"},
    {"names":["rack_dischargeable_cap"],"condition":"hour<=12","expression":"500-(12-hour)*40-second*1+Rand(1,10,1)"},
    {"names":["rack_dischargeable_cap"],"condition":"hour>12","expression":"(hour-12)*40+20+second*1+Rand(1,10,1)"},

    {"names":["tdy_AC_discharged_cap"],"condition":"","expression":"hour>12?(hour-12)*RandSeed(0.8,0.9,0.01,day):0"},
    {"names":["tdy_AC_charged_cap"],"condition":"","expression":"hour>12?0:(12-hour)*RandSeed(0.8,0.9,0.01,day)"},

   {"names":["fwd_active_total_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)"},
    {"names":["fwd_actives_sharp_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.1"},
    {"names":["fwd_active_peak_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.3"},
    {"names":["fwd_active_flat_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.4"},
    {"names":["fwd_active_valley_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.2"},
    {"names":["fwd_active_abyss_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0"},

    {"names":["bw_reactive_total_cap"],"condition":"","expression":"RandSeed(500,900,0.01,day)"},
    {"names":["bw_reactive_sharp_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.1"},
    {"names":["bw_reactive_peak_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.3"},
    {"names":["bw_reactive_flat_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.4"},
    {"names":["bw_reactive_valley_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0.2"},
    {"names":["bw_active_abyss_cap"],"condition":"","expression":"RandSeed(500,800,0.01,day)*0"},

    {"names":["tdy_AC_discharged_cap"],"condition":"","expression":"hour>12?(hour-12)**RandSeed(0.8,0.9,0.01,day):0"},
    {"names":["tdy_AC_charged_cap"],"condition":"","expression":"hour>12?0:(12-hour)*RandSeed(0.8,0.9,0.01,day)"},

    {"names":["total_AC_apparent_power"],"condition":"","expression":"timestamp-1717121200+RandSeed(10,100,1,hour)"},
    {"names":["total_AC_power_factor"],"condition":"","expression":"timestamp-1717121200+RandSeed(20,120,1,hour)"},
    {"names":["DC_power"],"condition":"","expression":"RandSeed(0.7,2,0.01,timestamp/101)"},

    {"names":["sample12"],"condition":"","expression":"ValueFile('C:/Users/w00995/Desktop/projects/yunjian-iot/demo-mock/iot-service/src/data/jobs/data_rules/dps/pcs_DC_voltage.csv')"},
    {"names":["sample13"],"condition":"","expression":"ValueFileAuto('C:/Users/w00995/Desktop/projects/yunjian-iot/demo-mock/iot-service/src/data/jobs/data_rules/dps/pcs_DC_voltage.csv')"}
]
}
`)
}

func NewMockDeviceTree(s string) MockDeviceTreeConfig {
	var d MockDeviceTreeConfig
	json.Unmarshal([]byte(s), &d)

	d.devicesMap = map[string]*MockDeviceTreeNode{}
	if d.ProductTypeCtr == nil {
		d.ProductTypeCtr = map[string]MockDeviceCtrOption{}
	}

	d.Devices.FillEmpty()
	d.Devices.Lookup(func(parent, node *MockDeviceTreeNode, i int) {
		if tmp, exist := d.ProductTypeCtr[node.ProductType]; exist {
			node.MockDeviceCtrOption = MergeMockDeviceCtrOption(node.MockDeviceCtrOption, tmp)
		}
		d.devicesMap[node.DeviceId] = node
	})

	return d
}

// MockDeviceTreeConfig 设备数配置
type MockDeviceTreeConfig struct {
	Devices        MockDeviceTree                 `json:"devices"`
	ProductTypeCtr map[string]MockDeviceCtrOption `json:"product_type_ctr"` //产品类型对应控制内容

	devicesMap map[string]*MockDeviceTreeNode //辅助生成的仿真数据节点，key={deviceId}，value=节点信息和配置
}

func (c MockDeviceTreeConfig) GetDeviceNode(deviceId string) (*MockDeviceTreeNode, bool) {
	tmp, exist := c.devicesMap[deviceId]
	return tmp, exist
}

// MockDeviceTree 模拟仿真用设备树信息
type MockDeviceTree []*MockDeviceTreeNode

type MockDeviceTreeNode struct {
	DeviceId    string `json:"device_id"`    //设备id
	DeviceName  string `json:"device_name"`  //设备名称
	ProductType string `json:"product_type"` //设备类型

	MockDeviceCtrOption //控制可选项

	Children MockDeviceTree `json:"children"` // 子设备
}

// FillEmpty 遍历树
func (tree MockDeviceTree) FillEmpty() {
	for k, v := range tree {
		if v.DeviceId == "" {
			tree[k].DeviceId = "fill_s_" + utils.RandLetterFigureCode(8)
		}
		if v.DeviceName == "" {
			tree[k].DeviceName = "fill_dev_" + v.ProductType + utils.RandLetterCode(6)
		}
		tree[k].Children.FillEmpty()
	}
}

// Find 找节点
func (tree MockDeviceTree) Find(id string) *MockDeviceTreeNode {
	var find *MockDeviceTreeNode
	tree.Lookup(func(parent *MockDeviceTreeNode, node *MockDeviceTreeNode, i int) {
		if find == nil && node.DeviceId == id {
			find = node
		}
	})
	return find
}

// Lookup 遍历树,f(parent,current,level)
func (tree MockDeviceTree) Lookup(f func(*MockDeviceTreeNode, *MockDeviceTreeNode, int)) {
	var lookupNodes func(parent *MockDeviceTreeNode, list MockDeviceTree, level int)
	lookupNodes = func(parent *MockDeviceTreeNode, list MockDeviceTree, level int) {
		for _, v := range list {
			f(parent, v, level)
			lookupNodes(v, v.Children, level+1)
		}
	}

	lookupNodes(nil, tree, 1)
}

type MockDeviceCtrOption struct {
	ThingModel     string `json:"thing_model"`     //指定物模型,空则取全局配置
	DataRule       string `json:"data_rule"`       //指定数据规则,空则取全局配置
	ReportProperty bool   `json:"report_property"` //是否上报属性
	ReportEvent    bool   `json:"report_event"`    //是否上报事件
	ReportOnline   bool   `json:"report_online"`   //是否上报在线状态
}

func MergeMockDeviceCtrOption(p1, p2 MockDeviceCtrOption) MockDeviceCtrOption {
	if p1.ThingModel == "" {
		p1.ThingModel = p2.ThingModel
	}
	if p1.DataRule == "" {
		p1.DataRule = p2.DataRule
	}
	if p2.ReportProperty {
		p1.ReportProperty = p2.ReportProperty
	}
	if p2.ReportEvent {
		p1.ReportEvent = p2.ReportEvent
	}
	if p2.ReportOnline {
		p1.ReportOnline = p2.ReportOnline
	}
	return p1
}

func TestMockDeviceTree() MockDeviceTreeConfig {
	return NewMockDeviceTree(`
{
  "devices": [
    {
      "device_id": "s_XM1SKU4WQ",
      "device_name": "总变压器",
      "product_type": "sys_transformer",
      "children": [
        {
          "device_id": "s_I3DU1QU",
          "device_name": "变压器节点-1",
          "product_type": "sys_transformer",
          "children": [
            {
              "device_id": "s_MX1NDI2IQ",
              "device_name": "储能并网点-1",
              "product_type": "sys_energy_point",
              "children": [
                {
                  "device_id": "s_AX32XI1Q",
                  "device_name": "堆-1",
                  "product_type": "sys_batterystack",
                  "children": [
                    {
                      "device_id": "s_UI2DKQ3U",
                      "device_name": "电表-1",
                      "product_type": "sys_meter"
                    },
                    {
                      "device_id": "s_XS2UQ903U",
                      "device_name": "空调-1",
                      "product_type": "sys_aircond"
                    },
                    {
                      "device_id": "s_OM3X1YQ",
                      "device_name": "推动环设备",
                      "product_type": "sys_node"
                    },
                    {
                      "device_id": "s_ZK2SI4DD",
                      "device_name": "直流汇聚点",
                      "product_type": "sys_node",
                      "children": [
                        {
                          "device_id": "s_LMS2IU3YQ",
                          "device_name": "簇-1",
                          "product_type": "sys_batterycluster",
                          "children": [
                            {
                              "device_id": "s_AX2KS4UW",
                              "device_name": "PCS",
                              "product_type": "sys_pcs"
                            },
                            {
                              "device_id": "s_SQ2IO3W",
                              "device_name": "BMS",
                              "product_type": "sys_bms"
                            },
                            {
                              "device_id": "s_CA2OS1X",
                              "device_name": "簇动环设备",
                              "product_type": "sys_node"
                            }
                          ]
                        },
                        {
                          "device_id": "s_WI1QIS3O",
                          "device_name": "簇-2",
                          "product_type": "sys_batterycluster",
                          "children": [
                            {
                              "device_id": "s_PO2WS31S",
                              "device_name": "PCS",
                              "product_type": "sys_pcs"
                            },
                            {
                              "device_id": "s_QO1SWE2E",
                              "device_name": "BMS",
                              "product_type": "sys_bms"
                            },
                            {
                              "device_id": "s_ZM2SII4Q",
                              "device_name": "簇动环设备",
                              "product_type": "sys_node"
                            }
                          ]
                        },
                        {
                          "device_id": "s_QY1OD33J",
                          "device_name": "簇-3",
                          "product_type": "sys_batterycluster",
                          "children": [
                            {
                              "device_id": "s_CJ1QIO89LA",
                              "device_name": "PCS",
                              "product_type": "sys_pcs"
                            },
                            {
                              "device_id": "s_OMI2UY3Q",
                              "device_name": "BMS",
                              "product_type": "sys_bms"
                            },
                            {
                              "device_id": "s_AW3UI1QO",
                              "device_name": "簇动环设备",
                              "product_type": "sys_node"
                            }
                          ]
                        },
                        {
                          "device_id": "s_JX9US28KQ",
                          "device_name": "消防-1",
                          "product_type": "sys_fes",
                          "children": []
                        }
                      ]
                    },
                    {
                      "device_id": "s_XM8LQ01P",
                      "device_name": "总PCS-1",
                      "product_type": "sys_pcs",
                      "children": []
                    },
                    {
                      "device_id": "s_M91JS1KW2",
                      "device_name": "总PCS-2",
                      "product_type": "sys_pcs",
                      "children": []
                    }
                  ]
                },
                {
                  "device_id": "s_ER2IW1QQ1",
                  "device_name": "堆-2",
                  "product_type": "sys_batterystack",
                  "children": [
                    {
                      "device_id": "s_NSQ2OS9OW",
                      "device_name": "空调-1",
                      "product_type": "sys_aircond"
                    },
                    {
                      "device_id": "s_XU3S99OQ",
                      "device_name": "消防-1",
                      "product_type": "sys_fes",
                      "children": []
                    },
                    {
                      "device_id": "s_0NBS2YU1Q",
                      "device_name": "簇-1",
                      "product_type": "sys_batterycluster",
                      "children": [
                        {
                          "device_id": "s_2IDU2Q2XX",
                          "device_name": "BMS-1",
                          "product_type": "sys_bms"
                        }
                      ]
                    },
                    {
                      "device_id": "s_HUW1UI27Q",
                      "device_name": "簇-2",
                      "product_type": "sys_batterycluster",
                      "children": [
                        {
                          "device_id": "s_O1MI8UU2S",
                          "device_name": "BMS-2",
                          "product_type": "sys_bms"
                        }
                      ]
                    },
                    {
                      "device_id": "s_A2M0X9MK",
                      "device_name": "簇-3",
                      "product_type": "sys_batterycluster",
                      "children": [
                        {
                          "device_id": "s_SO1WO23Q",
                          "device_name": "BMS-3",
                          "product_type": "sys_bms"
                        }
                      ]
                    }
                  ]
                }
              ]
            },
            {
              "device_id": "s_UW1MQM2KS",
              "device_name": "电表",
              "product_type": "sys_meter"
            }
          ]
        },
        {
          "device_id": "s_PSI4SQ05",
          "device_name": "变压器节点-2",
          "product_type": "sys_transformer",
          "children": [
            {
              "device_id": "s_UQ2KJ7WK",
              "device_name": "储能并网点-2",
              "product_type": "sys_energy_point"
            }
          ]
        },
        {
          "device_id": "s_YWD8IO8OQ",
          "device_name": "变压器节点-3",
          "product_type": "sys_transformer",
          "children": [
            {
              "device_id": "s_YW2UQI31W",
              "device_name": "储能并网点-3",
              "product_type": "sys_energy_point"
            }
          ]
        },
        {
          "device_id": "s_SKD2IWQ1IO",
          "device_name": "电表",
          "product_type": "sys_meter"
        }
      ]
    }
  ],
  "product_type_ctr": {
    "sys_bms": {
      "thing_model": "./data/jobs/thing_models/bms_model.json",
      "data_rule": "./data/jobs/data_rules/bms_model.json"
    },
    "sys_transformer": {
      "thing_model": "./data/jobs/thing_models/bms_model.json",
      "data_rule": "./data/jobs/data_rules/bms_model.json"
    }
  }
}
`)
}
